﻿# # # # # # # # # # # # # # # 
# CIVILIZ8N                 #
# Build a civilization      #
# in 10 turns               #
# # # # # # # # # # # # # # # 
# Hammurabi Highscores      #
# # # # # # # # # # # # # # #
# 1st fabio         185     #
# 2nd sunil         178     #
# 3rd tann          175     #
# 4th santiago      170     #
# send score pictures to    #
# tann@threechoicegames.com #
# # # # # # # # # # # # # # #

# consts and aliases
	# setting up the grid
	:const startX 22
	:const startY 4
	:const fiddlyStartX 21 #startX-1
	:const fiddlyEndX 117 #fiddlyStartX + 9 * 11 - 3
	:const fiddlyBotY 60 #startY + 8 * 7

	:const centerX 65
	:const centerY 28

	:const choiceStartX 3
	:const choiceTextX -2
	:const choiceTextY -4
	:const choiceStartY 28
	:const choiceGap 12

	:const textGap 5

	:const scoreX 1
	:const scoreY 3

	:const turnsX 4
	:const turnsY 10
	:const turnsGap 3

	# code reviewers hate it, one weird trick discovered by a single coder
	:const plusNothing 0b00000000 

	:const plusX 	0b00010000
	:const plus2X 	0b00100000
	:const plusY 	0b00000001
	:const plus2Y 	0b00000010

	:const minusX 	0b11110000
	:const minus2X 	0b11100000
	:const minusY 	0b11111111
	:const minus2Y 	0b11111110

	:const IDHut 0
	:const IDShrine 1
	:const IDLogger 2
	:const IDMeeting 3
	:const IDGarden 4
	:const IDTemple 5
	:const IDTree 6
	:const IDEmpty 7

	:const tileTypeMask 0b00000111

	# states
		:const state_choosingMode 4
		:const state_drawing 0
		:const state_waitingForInput 1
		:const state_redoInput 2
		:const state_gameEnd 3
		:const state_showingScore 5
		:const state_settingUp 6
		:const state_passedInput 7


	# aliases
		# I initially set up my aliases based on what I thought I'd need
		# Then I found that I wanted to store a lot more stuff in the registers
		# So I picked ones that wouldn't cause register collisions in those functions
		# That's why this is such a mess : (

		:alias keyPressed v0
		:alias splitX v0
		:alias splitY v1
		:alias tileTypeToSave v2
		:alias xySplit v3
		:alias counter2 v3
		:alias counter v4
		:alias surroundCheck v5
		:alias hexX v6
		:alias surroundTile v6
		:alias gardenScoreData v6
		:alias hexY v7
		:alias surroundIndex v7
		:alias gardenPosition v7
		:alias otherGroup v8
		:alias hexPosition2 v9
		:alias calculatedDistance v9
		:alias gardenData v9
		:alias distCalcHelper va
		:alias gardenShouldScore va
		:alias hexPosition va
		:alias mainGroup vb
		:alias drawX vb
		:alias templeSurround vb
		:alias tempTileType vc
		:alias drawY vc
		:alias foundGarden vc
		:alias gameState vd

# some data
	
	: hammurabiMode
	0

	: numTurns
	0

	: score
	0

	# tile location of the last tile placed
	: currentTile
	0
	
	# the number to be added to the score next scoreUpdate
	: scoreAdd
	0

	

	: decimalScore
	0 0 0

	# when I split a position byte into x/y positions, this stores the x/y
	: splitPositions
	0 0

	# 1, 2 or 3 depending on which tile you have selected
	: selectedTileIndex
	0

	# the tileTypes of the randomly-generated tiles you can pick
	: tileTypes
	0 0 0

	: turnNumber
	0

	# 1 or 0 depending on whether you should place a bonus hut!
	: extraHutsToPlace
	0

# garden group stuff
	
	# implementing the garden tile was a huge pain
	# when you place a garden tile, it adds itself to the list of gardens
	# it then checks around it to add itself to the group of gardens around it
	# if it doesn't find any, it assigns itself a new group
	# if it finds multiple, it merges the groups it finds
	# the group is stored in the tile data
	# bit 0 is whether it has scored bonus points or not
	# bits 1-4 are the group index
	# bits 5-7 are the tile type (this is the same for all tiles)

	# the highest set group
	: highestGroupIndex
		0

	# the number of tiles in each group
	: groupNumbers
		0 0 0 0 0 0 0 0 0 0 0 0 0

	# the highest set garden
	: highestGardenIndex
		0

	# all the gardens
	: allGardens
		0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

: tileStorage

	# this stores the actual tile data
	# tiles are mostly stored as positional pointers
	# to get tile data from the storage, you set i to tileStorage, increment it by your tile positional pointer and load it.
	# 0b10001000 is the center tile
	# 0b11110000 is the x coordinate
	# 0b00001111 is the y coordinate

	# 0xff is outside bounds
	# 0x07 is empty tile 
	# empty tile is 0x07 instead of 0x00 becuase it makes it easier if the placeable tiles are IDs 0-5

	# I'm tossing like 200 bytes away here but it's really convenient
	# I know that if a tile's data is 0xff then it is out of bounds
	# also I have a function that checks tiles within distance 2 and there is padding around the edge so that they are also out of bounds

	# check out the sweet PARALLELOGRAM of 0x07 valid tiles in the middle!
	# it's interesting that if you have a rectangular grid of hexagons, it's shaped like a parallelogram
	# and if you define a rectangular grid of hexagons, it looks like a parallelogram when stored as just x/y values
	
	0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 
	0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 
	0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 
	0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 
	0xff 0xff 0xff 0xff 0xff 0xff 0xff 0x07 0x07 0x07 0x07 0x07 0x07 0x07 0xff 0xff 
	0xff 0xff 0xff 0xff 0xff 0xff 0xff 0x07 0x07 0x07 0x07 0x07 0x07 0xff 0xff 0xff 
	0xff 0xff 0xff 0xff 0xff 0xff 0x07 0x07 0x07 0x07 0x07 0x07 0x07 0xff 0xff 0xff 
	0xff 0xff 0xff 0xff 0xff 0xff 0x07 0x07 0x07 0x07 0x07 0x07 0xff 0xff 0xff 0xff 
	0xff 0xff 0xff 0xff 0xff 0x07 0x07 0x07 0x07 0x07 0x07 0x07 0xff 0xff 0xff 0xff 
	0xff 0xff 0xff 0xff 0xff 0x07 0x07 0x07 0x07 0x07 0x07 0xff 0xff 0xff 0xff 0xff 
	0xff 0xff 0xff 0xff 0x07 0x07 0x07 0x07 0x07 0x07 0x07 0xff 0xff 0xff 0xff 0xff 
	0xff 0xff 0xff 0xff 0x07 0x07 0x07 0x07 0x07 0x07 0xff 0xff 0xff 0xff 0xff 0xff 
	0xff 0xff 0xff 0x07 0x07 0x07 0x07 0x07 0x07 0x07 0xff 0xff 0xff 0xff 0xff 0xff 
	0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 
	0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 
	0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff

# images 
	
	# 2x2 square for the turn tracker
	: turnBlip
		0b11000000
		0b11000000

	# text
		: textq
		0xc 0x12 0x12 0x14 0xa 
		: textw
		0x21 0x21 0x21 0x2d 0x12 
		: texte
		0xe 0x10 0x1c 0x10 0xe 
		: textd
		0x1c 0x12 0x12 0x12 0x1c 
		: texts
		0xe 0x10 0xc 0x2 0x1c 
		: texta
		0xc 0x12 0x1e 0x12 0x12 
		: text0
		0xc 0x12 0x12 0x12 0xc 
		: text1
		0x4 0xc 0x4 0x4 0x4 
		: text2
		0xc 0x12 0x4 0x8 0x1e 
		: text3
		0x1c 0x2 0xc 0x2 0x1c 
		: text4
		0x10 0x14 0x14 0x1e 0x4 
		: text5
		0x1e 0x10 0xc 0x2 0x1c 
		: text6
		0xe 0x10 0x1c 0x12 0xc 
		: text7
		0x1e 0x2 0x4 0x8 0x10 
		: text8
		0xc 0x12 0xc 0x12 0xc 
		: text9
		0xc 0x12 0xe 0x2 0xc 
		
	: placeableTiles
		: hut
			0x0 0xf 0x1f 0x3e 0x7f 0x3f 0x1b 0xf 
			0x0 0xf 0x1c 0x3c 0x7f 0x31 0x11 0xf 
			0x0 0xf0 0xf8 0xfc 0xfe 0xec 0xf8 0xf0 
			0x0 0xf0 0x78 0x7c 0xc6 0xc4 0xf8 0xf0 

		: shrine
			0x0 0xf 0x10 0x39 0x70 0x39 0x1b 0xf 
			0x0 0xf 0x10 0x3b 0x70 0x3b 0x1b 0xf 
			0x0 0xf0 0x8 0x9c 0xe 0x9c 0xd8 0xf0 
			0x0 0xf0 0x8 0xdc 0xe 0xdc 0xd8 0xf0 

		: logger
			0x0 0xf 0x1f 0x3d 0x78 0x37 0x1d 0xf 
			0x0 0xf 0x7 0x3f 0x7f 0x38 0x18 0xf 
			0x0 0xf0 0xf8 0xfc 0xfe 0x7c 0xf8 0xf0 
			0x0 0xf0 0x38 0xe4 0xfe 0xcc 0xf8 0x90 
			
		: meeting
			0x0 0xf 0x1c 0x3b 0x77 0x3b 0x1c 0xf 
			0x0 0xf 0x1c 0x39 0x73 0x39 0x1c 0xf 
			0x0 0xf0 0x38 0xdc 0xee 0xdc 0x38 0xf0 
			0x0 0xf0 0x38 0x9c 0xce 0x9c 0x38 0xf0 
		
		: garden
			0x0 0xf 0x19 0x34 0x70 0x38 0x1f 0xf 
			0x0 0xf 0x1e 0x3b 0x7f 0x37 0x18 0xf 
			0x0 0xf0 0x18 0x2c 0x8e 0x1c 0xf8 0xf0 
			0x0 0xf0 0xf8 0xdc 0x7e 0xec 0x18 0xf0 

		: temple
			0x0 0xe 0x1e 0x3c 0x7c 0x38 0x18 0xf 
			0x0 0xe 0x1e 0x3c 0x7d 0x38 0x1a 0xf 
			0x0 0x70 0x78 0x3c 0x3e 0x1c 0x18 0xf0 
			0x0 0x70 0x78 0x3c 0xbe 0x1c 0x58 0xf0 

		: trees
			0x0 0xc 0x3 0x23 0x7f 0x38 0x18 0xf 
			0x0 0xf 0x1e 0x3e 0x77 0x37 0x1f 0xd 
			0x0 0x40 0xc0 0xfc 0x8e 0x8c 0xf8 0xf0 
			0x0 0xf0 0xf8 0xec 0xfe 0xfc 0xd8 0xd0 			

: main
	hires
	#resetGame
	gameState := state_choosingMode
	drawTitle

	loop
		while gameState == state_choosingMode
		keyInput
	again
	
	: beginGame
	plane 1
	clear

	plane 2
	clear
	setupGame

	# main game loop
	loop
		: turn
		# check key input (blocking function)
		keyInput
		if gameState == state_redoInput then jump turn

		tilePlacementEffect
		checkSurroundingTiles
		incrementTurn
		updateScore

		if gameState == state_gameEnd then jump gameOver

		fillPickers
		randomiseChoices
		fillPickers

		# set hexPosition to CurrentTile
		i := currentTile
		load v0
		hexPosition := v0

		# draw controls from this position
		drawControls	

		# draw controls can trigger gameEnd if it find you trapped
		if gameState == state_gameEnd then jump gameOver
	again

: keyInput
	# Watch out, keyPressed is v0 so it won't stick around.
	keyPressed := key

	# this function is used for all keyInput in the game
	if gameState == state_choosingMode begin
		# 0 is X
		if keyPressed == 0 then return
		if keyPressed <= 3 begin
			# if the key is 1, 2, 3
			# number of turns is (key*5)+5
			v1 := keyPressed
			v0 += v0
			v0 += v0
			v0 += v1
			v0 += 5
			i := numTurns
			save v0
			gameState := state_settingUp
		end
		if keyPressed == 0x0C begin
			v0 := 10
			i := long numTurns
			save v0
			v0 := 1
			i := hammurabiMode
			save v0
			gameState := state_settingUp
		end
		return
	end

	# selecting a tile to place
	if keyPressed <= 3 begin
		gameState := state_redoInput
		# 0 is X
		if keyPressed == 0 then return
		# subtract one so it now refers to indexes 0, 1 and 2
		keyPressed += -1
		v1 := keyPressed
		i := selectedTileIndex
		load v0

		# pressed the same key again
		if v0 == v1 then return 

		v2 := v0
		v0 := v1

		# save the new selected index
		i := selectedTileIndex
		save v0

		# erase the current selection
		v0 := v2
		plane 2
		drawPickerText	
		
		# draw the new selection
		i := selectedTileIndex 
		load v0
		plane 2
		drawPickerText
		return
	end

	# check against key input block
	i := keyToIndex
	i += keyPressed
	load keyPressed

	# unrecognised key
	if keyPressed == 0xff begin
		gameState := state_redoInput
		return
	end

	# use the surrounding function with the correct index to get the specified tile
	surroundIndex := keyPressed
	surroundCheck := hexPosition
	nextSurroundingByte
	
	# set the new current tile position
	hexPosition2 := surroundTile
	v0 := surroundTile
	i := currentTile
	save v0

	getHexType
	
	# trying to place a tile on a used tile
	if v0 != IDEmpty begin 
		gameState := state_redoInput
		return
	end

	# undraw the controls
	drawControls

	# update the currentTile and draw it
	i := selectedTileIndex
	load v0
	i := tileTypes
	i += v0
	load v0
	tileTypeToSave := v0

	i := currentTile
	load v0
	hexPosition := v0
	saveTileData
	gameState := state_passedInput
	fillCurrentHex

	return

: drawTitle
	drawX := 0
	drawY := 0
	v3 := 8
	i := long titleScreen

	loop
		while drawX < 128
		drawY := 0
		loop
			while drawY < 64
			plane 1
			sprite drawX drawY 8
			
			
			i += v3
			plane 2
			sprite drawX drawY 8

			i += v3
			drawY += 8
		again
		drawX += 8
	again
	drawX := 0
	drawY := 0
	v3 := 0

	# have to set i back to 0 using long otherwise it doesn't reset the leftmost bits I think
	i := long 0

	return

# setup stuff

	: all_of_border_except_bottom_row
	0xf 0x10 0x20 0x40 0x80 0x40 0x20 0x10 0xf0 0x8 0x4 0x2 0x1 0x2 0x4 0x8 

	: bord_left 
	0b00011111		
	0b00100000
	0b01000000
	0b10000000

	: bord_right
	0b11100000
	0b00010000
	0b00001000
	0b00000100

	: bord_x_left
	0b10000000
	0b01000000
	0b00100000
	0b00010000

	: bord_x_right
	0b00000001
	0b00000010
	0b00000100
	0b00001000

	: bord_x_bot	
	0b11111111

	: setupGame
		
		gameState := state_drawing

		# first draw the outlines	
		drawOutlines
		

		# set the starting tile to the center
		v0 := 0b10001000
		i := currentTile
		save v0
		
		# setup starting tile to be shrine
		i := tileStorage
		i += v0
		v0 := 1
		save v0

		hexPosition :=  0b10001000

		# draw the starting hex
		fillCurrentHex

		# draw the picker outlines
		drawPickers

		# setup starting pickers
		randomiseChoices	
		fillPickers

		# draw the picker numbers
		drawAllPickerText

		# draw the highlighted picker number
		plane 2
		v1 := 0
		drawPickerText	

		# draw the score
		plane 1
		drawScore

		setupTurnBlips
		resetTurnCount

		setupTreePositions
		
		# draw the controls, ready to go!
		i := currentTile
		load v0
		hexPosition := v0
		drawControls

		return

	: drawOutlines
		# draw all the outlines of the tiles in the hex grid
		plane 1
		drawX := startX 
		drawY := startY

		: drawTops
			loop
				# draw top of hexagon split up into two parts
				i  := bord_left
				sprite drawX drawY 4
				drawX += 8
				i  := bord_right 	
				sprite drawX drawY 4
				drawX += 248		
				drawY += 8
				if drawY < 60 then 
			again
			
			# funny business because fuck hexagons
			drawX += 11
			v0 := 56
			drawY -= v0
			if drawY == startY begin
				drawY := startY
				drawY += 4
			else 
				drawY := startY
			end
			if drawX < 118 begin
				
				jump drawTops
				
			end
			

			# fiddly lr bits
			drawY := startY
			drawY += 4
			loop
				i := bord_x_left
				drawX := fiddlyStartX
				sprite drawX drawY 4

				i := bord_x_right
				drawX := fiddlyEndX
				sprite drawX drawY 4
				
				drawY += 8		
			if drawY < 60 then again

			# fiddly bot bits
			drawY := fiddlyBotY
			drawX := fiddlyStartX
			drawX += 4
			loop
				i := bord_x_bot
				sprite drawX drawY 1		
				drawX += 22		
			if drawX < 115 then again

			return

	: drawAllPickerText
		plane 1
		v0 := 0
		drawPickerText
		v0 := 1
		drawPickerText
		v0 := 2
		drawPickerText

		return

	: drawPickers
		# boring function that draws the outlines of the picker tiles
		# called once at the start of the game
		plane 1
		drawX := choiceStartX
		drawY := choiceStartY
		loop
			drawX := choiceStartX
			i := all_of_border_except_bottom_row
			sprite drawX drawY 8
			drawX += 8
			v0 := 8
			i += v0
			sprite drawX drawY 8
			drawX += 252
			drawY += 8
			i := bord_x_bot
			sprite drawX drawY 1
			drawY += 248
			drawY += choiceGap

		if drawY < 60 then again

		return

	: setupTreePositions
		# make 12 trees
		counter := 12
		loop
			while counter > 0

			# make sure the x coordinate is in bounds
			loop 
				splitX := random 0b00001111
				if splitX > 8 then again
			splitX += 252
				
			# make sure the y coordinate is in bounds
			loop
				splitY := random 0b00001111
				if splitY > 11 then again
			splitY += 251

			# addTree adds one to counter if it fails
			addTree
			counter += 255
			again

		return

	: addTree
		# keep track of potential x and y
		hexX := splitX
		hexY := splitY
	 
	 	# get the distance
		getHexDistance

		# fail if adjacent to starting location to avoid locking the player in. Plus it looks weird
		if calculatedDistance < 2 begin
			counter += 1
			return
		end

		# find the tile type byte
		splitXYToByte
		hexPosition := xySplit
		i := tileStorage
		i += hexPosition
		load v0

		# if it's occupied, fail
		if v0 != IDEmpty begin
			counter += 1
			return
		end

		# save tile type
		i := tileStorage
		i += hexPosition
		v0 := IDTree
		save v0

		# get the original x and y again
		xySplit := hexPosition
		splitByteToXY

		# draw the tree and we're DONE IM GONNA GO AND DO SOMETHING ELSE FOR A BIT NOW
		setDrawPositionsFromXY
		i := trees
		drawHexture

		return

	: setupTurnBlips
		i := numTurns
		load v0
		v6 := v0
		counter := 0
		loop
			while counter < v6
			i := turnNumber
			v0 := counter
			save v0
			drawTurnBlip
			counter += 1
		again

		return

	: resetTurnCount
		v0 := 0
		i := turnNumber
		save v0

		return

# drawing stuff

	: fillPickers
		# draw the insides of the tiles you can pick
		drawY := choiceStartY
		v1 := 0
		loop
			# get the index of tile at v1
			i := tileTypes
			i += v1
			load v0

			# navigate to the correct texture
			i := placeableTiles
			loop
				while v0 > 0 
				v0 += 255
				v2 := 32
				i += v2
			again

			drawX := choiceStartX
			drawHexture

			# increment the y draw position
			drawY += choiceGap
			v1 += 1
		if v1 < 3 then again

		return

	: drawPickerText
		# picker text is the 1|2|3 above the tiles
		drawX := choiceTextX
		drawY := choiceStartY
		v1 := choiceTextY
		drawY += v1
		i := text1
		if v0 > 0 begin
			loop
				v1 := 5
				i += v1
				drawY += choiceGap
				v0 += 255
			if v0 > 0 then again
		end
		sprite drawX drawY 5
		drawY += choiceGap

		return	

	: saveTileData
		i := tileStorage
		i += hexPosition
		v0 := tileTypeToSave
		save v0

		return

	: fillCurrentHex
		# takes hexPosition, checks what type it is and draws it

		# get the screen position
		xySplit := hexPosition
		splitByteToXY
		setDrawPositionsFromXY

		# load up the correct image
		i := tileStorage
		i += hexPosition
		load v0

		# other tile data is packed in the storage but at time of placement, it will always be 0
		# otherwise I would have to &= it with 0b00000111

		i := placeableTiles
		v1 := 32
		loop
			while v0 > 0
			i += v1
			v0 += -1
		again
		drawHexture

		return

	: drawHexture
		# just draws my 4-colour tile texture
		# assumes that i is set in the correct place and drawX and drawY are correctly-set
		# have do 4 draw calls, 2 with each bitplane
		v2 := 8
		plane 1
		sprite drawX drawY 8
		plane 2
		i += v2
		sprite drawX drawY 8
		i += v2
		drawX += 8
		plane 1
		sprite drawX drawY 8
		i += v2
		plane 2
		sprite drawX drawY 8

		return

	: drawControls
		# draws controls in surrounding free tiles
		plane 1
		surroundIndex := 0
		surroundCheck := hexPosition

		# v8 is used to check for game end
		# if no empty tiles surrounding current tile
		# then you are trapped!
		v8 := 0
		loop
			nextSurroundingByte
			hexPosition2 := surroundTile
			getHexType
			if v0 != IDEmpty begin
				# skips occupied tiles
			 	jump skipControlDraw
			end
			v8 := 1
			xySplit := surroundTile
			splitByteToXY
			setDrawPositionsFromXY
			i := textq
			v0 := surroundIndex
			v0 += 255
			i += v0
			i += v0
			i += v0
			i += v0
			i += v0
			drawX += 3
			drawY += 2
			sprite drawX drawY 5
			: skipControlDraw
		if surroundIndex < 6 then again

		if v8 == 0 then gameState := state_gameEnd

		return

	: drawScore
		# updates the visible score counter
		i := score
		load v0
		i := decimalScore
		bcd v0
		i := decimalScore

		# would be nice not to have to load them into registers and do all these checks
		# but I'm drawing stuff based on the data I get so I can't use the fact that i auto-increments

		load v2
		drawX := scoreX
		drawY := scoreY

		# v3 counter keeps track of which digit to be drawing
		v3 := 0

		loop		
			while v3 < 3 # <3<3<3
			# get the correct digit
			if v3 == 0 then v5 := v0
			if v3 == 1 then v5 := v1
			if v3 == 2 then v5 := v2
			
			# 5 bytes between each digit's image
			i := text0	
			i += v5
			i += v5
			i += v5
			i += v5
			i += v5

			sprite drawX drawY 5
			drawX += textGap
			v3 += 1
		again
			
		return

	: drawTurnBlip
		# this function is used to draw the intial turn blips
		# and also to light up the used turns
		# plane 1 or plane 2 beforehand change how this draws the blips
		i := turnNumber 
		drawX := turnsX
		drawY := turnsY
		load v0
		loop
			while v0 > 4
			drawY += turnsGap
			v0 += -5
		again
		loop
			while v0 > 0
			drawX += turnsGap
			v0 += -1
		again

		i := turnBlip
		sprite drawX drawY 2

		return

# place tile effects

	: tilePlacementJumpTable
		jump placeHut 
		jump placeShrine
		jump placeLogger 
		jump placeMeeting 
		jump placeGarden 
		jump placeTemple

	: tilePlacementEffect
		# called after placing the new tile
		i := currentTile
		load v0
		i := tileStorage
		i += v0
		load v0
		v0 <<= v0

		# each instruction in the jump table is 2 bytes, so if we double the tile type value, we can jump to the correct function

		jump0 tilePlacementJumpTable

	: checkSurroundingTiles
		# called after the placement effect resolves
		# checks surrounding tiles for any extra effects that should resolve
		i := currentTile
		load v0
		hexPosition := v0
		surroundCheck := v0
		surroundIndex := 0
		loop
			while surroundIndex < 6
			nextSurroundingByte
			i := tileStorage
			i += surroundTile
			load v0
			v1 := tileTypeMask
			v0 &= v1
			
			hexPosition2 := surroundTile
			
			# can't use a jump table here because I need to keep looping!
			if v0 == IDMeeting begin
				addToMeeting
				else if v0 == IDTemple begin
					addToTemple
				end
			end
		again

		return

	: placeHut
		v1 := 1
		addToScore
		i := extraHutsToPlace
		load v0
		# set v0 to be (1 - extraHutsToPlace)
		# so essentially flip it between 1 and 0
		v1 := 1
		v1 -= v0
		v0 := v1
		i := extraHutsToPlace
		save v0
		
		return

	: placeLogger
		v1 := 1
		addToScore

		# deforest surrounding tiles
		i := currentTile
		load v0
		surroundCheck := v0
		counter := 0
		surroundIndex := 0
		loop 
			while counter < 6
			nextSurroundingByte
			i := tileStorage
			i += surroundTile
			load v0
			v1 := tileTypeMask
			v0 &= v1
			if v0 == IDTree begin
				hexPosition := surroundTile
				fillCurrentHex
				tileTypeToSave := IDEmpty
				saveTileData
				v1 := 1
				addToScore
			end
			counter += 1
		again

		return

	: placeMeeting
		# gain one point
		v1 := 1
		addToScore

		# call addToMeeting for each surrounding tile
		i := currentTile
		load v0
		surroundCheck := v0
		surroundIndex := 0
		hexPosition2 := v0
		loop
			while surroundIndex < 6
			nextSurroundingByte
			i := tileStorage
			i += surroundTile
			load v0
			v1 := tileTypeMask
			v0 &= v1
			if v0 < 6 begin # all placeable tiles are 0-5
				addToMeeting
			end
			again

		return

		: addToMeeting
			# get the tile stats
			i := tileStorage
			i += hexPosition2
			load v0

			# add "1" to it (the number of surrounding tiles is stored in 0b11100000)
			v0 += 0b00100000
			
			# make a copy of it
			v1 := v0
			# and it to get only the surround matrix
			v2 := 0b11100000
			v1 &= v2

			# resave the tile stats
			i := tileStorage
			i += hexPosition2
			save v0

			# check if the tile is surrounded. +5 points if it is!
			if v1 == 0b11000000 begin
				v1 := 5
				addToScore
			end
			
			return

	: placeTemple
		i := currentTile
		load v0
		surroundCheck := v0
		surroundIndex := 0
		hexPosition2 := v0
		loop
			: templeLoop
			while surroundIndex < 6
			nextSurroundingByte
			i := tileStorage
			i += surroundTile
			load v0
			if v0 == 255 then jump templeLoop
			v1 := tileTypeMask
			v0 &= v1
			if v0 < 6 begin # all placeable tiles are 0-5
				hexPosition := surroundTile
				addToTemple
			end
			again

		return

		: addToTemple

			# hexPosition is the tile
			# hexPosition2 is the temple

			# get the tileType of the tile
			i := tileStorage
			i += hexPosition
			load v0
			v1 := tileTypeMask
			v0 &= v1
			tempTileType := v0

			# temples don't count for temple bonuses (this is mostly because I only have 5 bits for tileData and there are 6 tiles)
			if tempTileType == IDTemple then return 

			# extract the tiledata from the temple
			i := tileStorage
			i += hexPosition2
			load v0
			v0 >>= v0
			v0 >>= v0
			v0 >>= v0
			templeSurround := v0

			# shift v0 to be the correct bit to check against the temple data
			v0 := 1
			loop
				while tempTileType > 0
				tempTileType += -1
				v0 <<= v0
			again

			tempTileType := v0
			
			v0 &= templeSurround

			# already has this type next to it
			if v0 != 0 then return 

			# the types are different so increment score
			v1 := 1
			addToScore

			# and update the temple data
			templeSurround |= tempTileType

			templeSurround <<= templeSurround
			templeSurround <<= templeSurround
			templeSurround <<= templeSurround
			templeSurround += IDTemple

			i := tileStorage
			i += hexPosition2
			v0 := templeSurround
			save v0

			return

	: placeShrine
		i := currentTile
		load v0
		surroundCheck := v0
		surroundIndex := 0
		hexPosition2 := v0
		loop
			while surroundIndex < 18
			nextSurroundingByte
			i := tileStorage
			i += surroundTile
			load v0
			v1 := tileTypeMask
			v0 &= v1
			# found a shrine within 2 tiles so cancel
			if v0 == IDShrine then return 
		again

		# ok, no shrines within 2 so have points
		v1 := 5
		addToScore

		return

	: placeGarden
		# garden tileData byte is...
		# 0b10000000 score bit. 1 if scored as 3, 0 otherwise
		# 0b01111000 group bits
		# 0b00000111 tileType bits, all tiles have this

		# I'm pretty scared to refactor this, it was a huge pain to code and I don't want to break it

		# first add 2 points
		v1 := 2
		addToScore

		# get the garden index, save it and increment the stored version by 1
		i := highestGardenIndex
		load v0
		v1 := v0
		v0 += 1
		i := highestGardenIndex
		save v0

		# save the position of this garden in the list
		i := allGardens
		i += v1
		v0 := hexPosition
		save v0

		# then loop through adjacent tiles and look for gardens
		i := currentTile
		load v0
		surroundCheck := v0
		surroundIndex := 0
		hexPosition := v0
		foundGarden := 0
		mainGroup := 255
		loop
			while surroundIndex < 6
			nextSurroundingByte
			i := tileStorage
			i += surroundTile
			load v0
			# get the tileType part of the data
			v1 := tileTypeMask
			v0 &= v1

			if v0 == IDGarden begin
				# found a garden
				i := tileStorage
				i += surroundTile
				load v0
				# mask it to get the group index
				v1 := 0b01111000
				v0 &= v1
				otherGroup := v0

				# just-placed garden is ungrouped
				if mainGroup == 255 begin
					# join that group
					i := tileStorage
					i += surroundTile
					load v0

					# get the group index
					v1 := 0b01111000
					v0 &= v1
					mainGroup := v0

					# set my group to be it
					i := tileStorage
					i += hexPosition
					load v0
					v0 |= mainGroup

					# save me
					i := tileStorage
					i += hexPosition
					save v0
				end
				if mainGroup != otherGroup begin
					# already joined a group but found another tile!!!
					# need to merge the groups	
					mergeGroups
				end
				foundGarden := 1
			end
		again

		if foundGarden == 0 begin
			# need to give the tile a group
			i := highestGroupIndex
			load v0
			v0 <<= v0
			v0 <<= v0
			v0 <<= v0
			mainGroup := v0

			i := tileStorage
			i += hexPosition
			load v0

			# save the group number to the tile
			v0 += mainGroup
			i := tileStorage
			i += hexPosition
			save v0

			# increment the highest group index
			# I think I may be wasting empty groups here
			# but I think it's quicker to just waste them
			i := highestGroupIndex
			load v0
			v0 += 1
			i := highestGroupIndex
			save v0
		end

		# increment the number of tiles in the group
		i := groupNumbers
		i += mainGroup
		load v0
		v0 += 1
		i := groupNumbers
		i += mainGroup
		save v0

		gardenShouldScore := v0
		if gardenShouldScore != 3 then gardenShouldScore := 0
		if gardenShouldScore == 3 then gardenShouldScore := 1
		
		# check all the tiles of the main group
		# if they should be scored as 3 and aren't, add 2 pts
		# if they should be scored as 1 and aren't, subtract 2 pts

		# garden position holds the position pointer to the garden I'm checking from the group list
		i := allGardens
		load v0
		gardenPosition := v0
		i := tileStorage
		i += v0
		load v0
		gardenData := v0
		counter := 0
		loop
			# if it's 0 then I've checked all the gardens in the group
			while gardenPosition != 0
			v1 := 0b01111000
			v0 &= v1
			if v0 == mainGroup begin
				v1 := 0b10000000
				gardenScoreData := gardenData
				gardenScoreData &= v1
				if gardenScoreData != gardenShouldScore begin

					if gardenShouldScore == 1 begin
						v1 := 2
						addToScore
					end

					if gardenShouldScore == 0 begin
						v1 := -2
						addToScore
					end

					# save the score bit
					v1 := 0b10000000
					if gardenShouldScore == 0 then gardenData -= v1
					if gardenShouldScore == 1 then gardenData += v1
					i := tileStorage
					i += gardenPosition
					v0 := gardenData
					save v0
				end
			end
			counter += 1
			i := allGardens
			i += counter
			load v0
			gardenPosition := v0
			i := tileStorage
			i += v0
			load v0
			gardenData := v0

		again

		return

		: mergeGroups
			i := highestGardenIndex
			load v0
			counter2 := v0
			counter := 0
			loop
				while counter < counter2

				# get the pointer to the tile
				i := allGardens
				i += counter
				load v0

				# get the actual tile
				i := tileStorage
				i += v0
				load v0

				# keep a copy of it in v2
				v2 := v0

				# check if the group is othergroup
				v1 := 0b01111000
				v0 &= v1
				if v0 == otherGroup begin
					# found one

					# increment the number in the group
					i := groupNumbers
					i += mainGroup
					load v0
					v0 += 1
					i := groupNumbers
					i += mainGroup
					save v0

					# update the tileData
					i := allGardens
					i += counter
					load v0
					
					i := tileStorage
					i += v0

					# replace the tile's group with mainGroup and save it
					v1 := 0b10000111
					v2 &= v1
					v2 += mainGroup
					v0 := v2

					save v0
				end
				counter += 1 
			again

			return

: nextSurroundingByte
	# I'm jumping to the correct instructions to alter surroundTile to point to the right tile
	# It goes round in a circle, top left, top, top right etc
	# I keep track of surroundIndex so I can get the next tile around easily
	surroundTile := surroundCheck
	surroundingHelperFunction
	surroundIndex += 1

	return

: surroundingHelperFunction
	
	# so each routine is 6 bytes, xChange, yChange, return (2 bytes each)
	# that means I need to multiply v0 by 6 to jump to the right place

	v0 := surroundIndex

	# multiply by 4 by shifting twice
	v0 <<= v0
	v0 <<= v0
	# get to 6 by adding twice
	v0 += surroundIndex
	v0 += surroundIndex

	# I'm using this helper function because I want to use a jump0 call but also increment surroundIndex afterwards

	jump0 surroundJumpTableIsh

: surroundJumpTableIsh

	# if x or y is not changing, I have to put a dummy instruction in so it all lines to 6-byte-blocks

	# 0
	surroundTile += minusX
	surroundTile += plusNothing
	return

	# 1
	surroundTile += minusY
	surroundTile += plusNothing
	return

	# 2
	surroundTile += plusX
	surroundTile += minusY
	return

	# 3
	surroundTile += plusX
	surroundTile += plusNothing
	return
	
	# 4
	surroundTile += plusY
	surroundTile += plusNothing
	return
		
	# 5
	surroundTile += minusX
	surroundTile += plusY
	return
	

	# distance 2

	# 6-17 is the 12 tiles distance 2 from surroundCheck

	# tile x is stored in 0b11110000
	# tile y is stored in 0b00001111

	# maximum tile x is 0b1100 so won't overflow with +2
	# minimum tile x is 0b0100 so won't underflow with -2

	# maximum tile y is 0b1101 so won't overflow with +2
	# minimum tile y is 0b0101 so won't underflow with -2


	#6
	surroundTile += minus2X
	surroundTile += plusNothing
	return

	#7
	surroundTile += minusX
	surroundTile += minusY
	return

	#8
	surroundTile += minus2Y
	surroundTile += plusNothing
	return

	#9
	surroundTile += minus2Y
	surroundTile += plusX
	return
	
	#10
	surroundTile += minus2Y
	surroundTile += plus2X
	return

	#11
	surroundTile += minusY
	surroundTile += plus2X
	return
		
	#12
	surroundTile += plus2X
	surroundTile += plusNothing
	return
	
	#13
	surroundTile += plusX
	surroundTile += plusY
	return

	#14
	surroundTile += plus2Y
	surroundTile += plusNothing
	return

	#15
	surroundTile += minusX
	surroundTile += plus2Y
	return

	#16	
	surroundTile += minus2X
	surroundTile += plus2Y
	return
	
	#17
	surroundTile += minus2X
	surroundTile += plusY
	return

: splitByteToXY

	# tile locations encode x/y positions in one byte
	# this splits it into x/y and saves that to splitPositions

	# x portion
	v0 := xySplit
	v2 := 0b11110000
	v0 &= v2
	v0 >>= v0
	v0 >>= v0
	v0 >>= v0
	v0 >>= v0

	# y portion
	v1 := xySplit
	v2 := 0b00001111
	v1 &= v2
	
	# offset so the center is 0,0 ish
	v2 := 8
	v0 -= v2
	v1 -= v2

	i := splitPositions
	save v1

	return

: setDrawPositionsFromXY

	# convenience function to convert grid coordinates into screen coordinates
	drawX := centerX
	drawY := centerY
	i := splitPositions
	load v1

	v2 := splitX
	v2 <<= v2
	v2 <<= v2
	# drawY += splitX * 4
	drawY += v2 

	v2 <<= v2
	v2 += splitX
	v2 += splitX
	v2 += splitX
	# drawX += splitX * 11
	drawX += v2

	v2 := splitY
	v2 <<= v2
	v2 <<= v2
	v2 <<= v2
	# drawY += splitY * 8
	drawY += v2

	return

: random6
	# bad little random 0-5 generator
	loop
		v0 := random 0b00000111
	if v0 > 5 then again

	return

: randomiseChoices
	i := extraHutsToPlace
	load v0
	if v0 > 0 begin
		generateExtraHuts
		return
	end

	# generate 3 numbers from 0-5 and save them in the choice slots
	i := tileTypes
	random6
	v2 := v0
	random6
	v1 := v0
	random6
	save v2

	return
		
	: generateExtraHuts
		# if placing extra huts, set all tileTypes to 0
		v0 := 0
		v1 := 0
		v2 := 0
		i := tileTypes
		save v2

		return

: getHexType
	# all hex types are stored in storage
	i := tileStorage
	i += hexPosition2
	v0 := 1
	load v0

	return

: addToScore
	# need to use scoreAdd so I can keep track of what the score was, undraw it, add everything at once to it, then rewdraw it
	# v1 should be set to score delta before calling this

	i := scoreAdd
	load v0
	v0 += v1
	i := scoreAdd
	save v0

	return

: updateScore
	plane 1
	drawScore

	i := score
	load v0
	v1 := v0
	i := scoreAdd
	load v0
	v0 += v1
	i := score
	save v0

	i := scoreAdd
	v0 := 0
	save v0

	drawScore	

	return

: getHexDistance
	# hex distance is max(abs(x), abs(y), abs(x+y)),  which is a bit tricky to translate to chip8...
	calculatedDistance := 0

	# x+y
	v2 := hexX
	v2 += hexY	

	# abs x
	if hexX > 200 begin
		distCalcHelper := hexX
		hexX -= distCalcHelper
		hexX -= distCalcHelper
	end

	# abs y
	if hexY > 200 begin
		distCalcHelper := hexY
		hexY -= distCalcHelper
		hexY -= distCalcHelper
	end

	# abs x+y
	if v2 > 200 begin
		distCalcHelper := v2
		v2 -= distCalcHelper
		v2 -= distCalcHelper
	end

	# calculate max
	if hexX > calculatedDistance then calculatedDistance := hexX
	if hexY > calculatedDistance then calculatedDistance := hexY
	if v2 > calculatedDistance then calculatedDistance := v2

	return

: splitXYToByte
	# 0b10001000 is treated as 0,0 because I liked centered grids!
	xySplit := splitX
	xySplit += 8
	xySplit <<= xySplit
	xySplit <<= xySplit
	xySplit <<= xySplit
	xySplit <<= xySplit
	xySplit += splitY
	xySplit += 8

	return

: incrementTurn
	# check if it's a bonus hut turn
	i := extraHutsToPlace
	load v0

	# if it is, skip it
	if v0 == 1 then return

	# highlight next turn blip
	plane 2
	drawTurnBlip

	# load max turns into v1
	i := numTurns
	load v0
	v1 := v0

	# increment turn counter
	i := turnNumber
	load v0
	i := turnNumber
	v0 += 1
	save v0

	# if turn number == maxTurns then end
	if v0 == v1 then gameState := state_gameEnd

	return

: keyToIndex
	0xff 0xff 0xff 0xff 0 1 2 5 4 3 0xff 0xff 0xff 0xff 0xff 0xff 0xff 

: gameOver
	# check to see if player is doing hammurabi mode
	i := hammurabiMode
	load v0
	if v0 != 0 begin
		i := numTurns
		load v0
		# final hammurabi mode is 20 turns
		if v0 != 20 begin
			# if not finished, immediately start new level
			resetGame
			jump beginGame
		end

		# if in final level of hammurabi mode, unset hammurabi mode
		i := hammurabiMode
		v0 := 0
		save v0
	end
	fillPickers
	gameState := state_showingScore

	# secret anti-cheat measure
	i := score
	v0 := 0
	v1 := 63
	plane 1
	sprite v0 v1 1

	plane 2
	loop
		# flash the score
		v0 := 10
		delay := v0
		loop
			v0 := delay
			if v0 != 0 then
		again
		drawScore
		v6 := 0xd

		# check if r is held to restart the game
		if v6 key then jump after
	again

	: after
	resetGame
	jump main

# reset
	
	: blankBytes 
		0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

	: fullBytes
		255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 

	: sevenBytes
		7 7 7 7 7 7 7

	: resetGame
		# clear the whole screen
		plane 2	
		clear
		plane 1	
		clear

		# check hammurabiMode
		i := hammurabiMode
		load v0
		if v0 == 1 begin
			# if set, increment turns by 5
			i := numTurns
			load v0
			v0 += 5
			i := numTurns
			save v0
		else 
			# otherwise, clear the score
			i := score
			v0 := 0
			save v0
		end

		i := blankBytes
		load vf
		i := currentTile

		# save over all of "some data"
		save vc

		# save over all garden data
		save vf
		save vf

		# load up null tile bytes
		i := fullBytes
		load vf

		i := tileStorage

		# save over all tile data
		save vf
		save vf
		save vf
		save vf
		save vf
		save vf
		save vf
		save vf
		save vf
		save vf
		save vf
		save vf
		save vf
		save vf
		save vf
		save vf
		
		# load up empty tile bytes
		i := sevenBytes
		load v6

		# setup empty useable tiles
		# navigate to correct point in data
		va := 16
		i := tileStorage
		i += va
		i += va
		i += va
		i += va
		va := 7
		i += va

		va := 9
		vb := 10

		# have to toggle between 9 and 10 spaces because hex grids
		save v6
		i += va
		save v5
		i += va
		save v6
		i += va
		save v5
		i += va
		save v6
		i += va
		save v5
		i += va
		save v6
		i += va
		save v5
		i += va
		save v6

		return


# maybe I could get to <3.5k if I optimised this and some of my other data stores
# but I'm already using 4 colours and hires so it doesn't feel like a big goal
: titleScreen
	0x0 0x7c 0x7c 0x38 0x38 0x10 0x10 0x11 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x13 0x11 0x10 0x10 0x10 0x10 0x10 0x0 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x0 0x18 0x1e 0x1f 0x1e 0x18 0x1 0x7d 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x7c 0x38 0x38 0x10 0x10 0x10 0x10 0x10 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x0 0x7c 0x7c 0x38 0x3b 0x13 0x13 0x13 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x13 0x10 0x13 0x10 0x13 0x13 0x13 0x13 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x13 0x0 0x1 0x2 0x6 0xc 0x1d 0x39 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x71 0x39 0x1d 0xc 0x6 0x2 0x1 0x0 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x0 0x0 0x8 0x10 0x31 0x63 0xe7 0xce 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x9c 0xce 0xe7 0x63 0x31 0x10 0x8 0x0 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x0 0x0 0x0 0xff 0x0 0x7 0xf7 0xf3 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0xe3 0xe1 0x41 0x41 0x41 0x41 0x41 0x41 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x0 0x0 0x0 0x0 0x0 0xc0 0xff 0xc0 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x0 0x3 0xff 0x3 0x0 0xc0 0xff 0xc0 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x0 0x0 0x0 0x0 0x0 0x0 0x80 0xe0 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0xff 0xe0 0x80 0x0 0x0 0x0 0x0 0x0 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x0 0x0 0x40 0x80 0x80 0x0 0x0 0x0 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x0 0x0 0x0 0x0 0x80 0x80 0x40 0x0 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x0 0x0 0x0 0xc0 0x0 0xc0 0xc0 0x80 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x80 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x0 0x0 0xf 0x8 0x9 0x9 0xc9 0x9 
	0x0 0x0 0x0 0x0 0x1 0x1 0x1 0x1 
	0xc9 0xc8 0xcf 0xc0 0xc0 0x0 0xc0 0x0 
	0x1 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x0 0xf 0x8 0xb 0x8 0xb 0x8 0xb 
	0x0 0x0 0x0 0x3 0x0 0x3 0x0 0x3 
	0xc8 0xf 0x0 0x0 0x0 0x0 0x0 0x0 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x0 0x0 0x0 0x1 0x3 0x6 0xc 0x8 
	0x0 0x0 0x0 0x1 0x3 0x6 0xc 0x8 
	0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 
	0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 
	0x8 0x8 0x4 0x7 0x1 0x0 0x0 0x0 
	0x8 0x8 0x4 0x7 0x1 0x0 0x0 0x0 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x0 0x7 0xe5 0x25 0x25 0x25 0x20 0x25 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x25 0x25 0xe5 0x5 0x0 0x0 0x0 0x0 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x7 0xe5 0x27 0xa5 0xa7 0xa0 0xa7 0xa1 
	0x0 0x0 0x0 0x80 0x80 0x80 0x80 0x80 
	0x27 0xe4 0x7 0x0 0x0 0x0 0x0 0x0 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x0 0x0 0x0 0xf8 0xe 0x2 0x2 0x6 
	0x0 0x0 0x0 0xf8 0xe 0x2 0x2 0x6 
	0xc 0x8 0x0 0x0 0x0 0x0 0x0 0x0 
	0xc 0x8 0x0 0x0 0x0 0x0 0x0 0x0 
	0x0 0x0 0x0 0x1 0xff 0x0 0x0 0x0 
	0x0 0x0 0x0 0x1 0xff 0x0 0x0 0x0 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x0 0x5d 0x55 0x55 0x55 0x55 0x0 0xc7 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x42 0x42 0x42 0xc2 0x0 0x0 0x0 0x0 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x77 0x55 0x77 0x55 0x57 0x0 0x71 0x50 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x50 0x50 0x70 0x0 0x0 0x0 0x0 0x0 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x0 0x0 0x40 0x0 0x0 0x0 0x0 0x42 
	0x0 0x0 0x40 0x0 0x0 0x0 0x0 0x42 
	0xc2 0xc6 0xc5 0xfd 0x38 0x0 0x0 0x0 
	0xc2 0xc6 0xc5 0xfd 0x38 0x0 0x0 0x0 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x0 0xd5 0x15 0xd5 0x15 0xc9 0x0 0x57 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x55 0x57 0x56 0x75 0x0 0x0 0x0 0x0 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x54 0x54 0x74 0x14 0x77 0x0 0xd5 0x95 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x95 0x95 0x9d 0x0 0x0 0x0 0x0 0x0 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x0 0x0 0x2 0x0 0x0 0x0 0x12 0x3e 
	0x0 0x0 0x2 0x0 0x0 0x0 0x12 0x3e 
	0x26 0x66 0x46 0x82 0x83 0x0 0x0 0x0 
	0x26 0x66 0x46 0x82 0x83 0x0 0x0 0x0 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x0 0xd4 0x14 0xdc 0x14 0xd4 0x0 0x77 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x54 0x57 0x51 0x57 0x0 0x0 0x0 0x0 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x77 0x55 0x55 0x55 0x75 0x0 0xdd 0x55 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0xd5 0x94 0x55 0x0 0x0 0x0 0x0 0x0 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x0 0x0 0x0 0x0 0x20 0x20 0x30 0x10 
	0x0 0x0 0x0 0x0 0x20 0x20 0x30 0x10 
	0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 
	0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 
	0x10 0x30 0x38 0x2d 0xe7 0x0 0x0 0x0 
	0x10 0x30 0x38 0x2d 0xe7 0x0 0x0 0x0 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x0 0x0 0x7 0x4 0x5 0x4 0x5 0x5 
	0x0 0x0 0x0 0x0 0x1 0x0 0x1 0x1 
	0x5 0x4 0x7 0x0 0x0 0x0 0x0 0x0 
	0x1 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x0 0x7 0x4 0x5 0x5 0x5 0xc4 0x4 
	0x0 0x0 0x0 0x1 0x1 0x1 0x0 0x0 
	0xc4 0x47 0xc0 0x0 0x0 0x0 0x0 0x0 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x0 0x0 0x20 0x0 0x0 0x0 0x0 0x20 
	0x0 0x0 0x20 0x0 0x0 0x0 0x0 0x20 
	0x60 0x61 0xe3 0xae 0x38 0x0 0x0 0x0 
	0x60 0x61 0xe3 0xae 0x38 0x0 0x0 0x0 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x0 0x3 0xf2 0x13 0xd2 0x52 0xd0 0x12 
	0x0 0x0 0x0 0x0 0xc0 0x40 0xc0 0x0 
	0xd2 0x12 0xf2 0x2 0x0 0x0 0x0 0x0 
	0xc0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x2 0xf2 0x13 0x52 0x52 0xd0 0x53 0x52 
	0x0 0x0 0x0 0x40 0x40 0xc0 0x40 0x40 
	0x13 0xf2 0x2 0x0 0x0 0x0 0x0 0x0 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x0 0x0 0x0 0x0 0x0 0xf 0x18 0x31 
	0x0 0x0 0x0 0x0 0x0 0xf 0x18 0x31 
	0x43 0x86 0xc 0x18 0x1f 0x0 0x0 0x0 
	0x43 0x86 0xc 0x18 0x1f 0x0 0x0 0x0 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x0 0xbb 0xa2 0xbb 0x23 0x3a 0x0 0xe7 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x82 0xe2 0x22 0xe2 0x0 0x0 0x0 0x0 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0xba 0xab 0xba 0xaa 0xaa 0x0 0xa9 0xa8 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0xa9 0xa8 0xa9 0x0 0x0 0x0 0x0 0x0 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x0 0x0 0x0 0x0 0x1 0x7 0xc 0x8 
	0x0 0x0 0x0 0x0 0x1 0x7 0xc 0x8 
	0x8 0xc 0x4 0x2 0x3 0xc3 0xc4 0x8c 
	0x8 0xc 0x4 0x2 0x3 0xc3 0xc4 0x8c 
	0x8 0x8 0xc 0x7 0xff 0x0 0x0 0x0 
	0x8 0x8 0xc 0x7 0xff 0x0 0x0 0x0 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x0 0xbb 0xa2 0xbb 0xa 0xbb 0x0 0x57 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x55 0x57 0x56 0x75 0x0 0x0 0x0 0x0 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0xaa 0xba 0xaa 0xaa 0xab 0x0 0xc0 0x40 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0xc0 0x40 0xc0 0x0 0x0 0x0 0x0 0x0 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x0 0x0 0x0 0x0 0xf0 0x18 0x8 0x8 
	0x0 0x0 0x0 0x0 0xf0 0x18 0x8 0x8 
	0x10 0x30 0x60 0xc0 0x0 0x80 0xc0 0x21 
	0x10 0x30 0x60 0xc0 0x0 0x80 0xc0 0x21 
	0x21 0x23 0x27 0xed 0xf9 0x0 0x0 0x0 
	0x21 0x23 0x27 0xed 0xf9 0x0 0x0 0x0 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x0 0xbb 0x2a 0xba 0x22 0xa3 0x0 0x77 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x54 0x57 0x51 0x57 0x0 0x0 0x0 0x0 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0xbb 0xaa 0xbb 0xb2 0xaa 0x0 0x0 0x0 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x0 0x0 0x0 0x0 0x0 0x70 0xd8 0x88 
	0x0 0x0 0x0 0x0 0x0 0x70 0xd8 0x88 
	0x88 0x8 0x8 0x8 0x8 0x0 0x0 0x0 
	0x88 0x8 0x8 0x8 0x8 0x0 0x0 0x0 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x0 0xa2 0xa2 0xa2 0xa2 0xba 0x0 0x0 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0xb2 0xaa 0xba 0xaa 0xb2 0x0 0x0 0x0 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x0 0x3 0x3 0x1 0x1 0x0 0x0 0x0 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x3 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x3 0x1 0x1 0x0 0x0 0x0 0x0 0x0 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x0 0xe3 0x83 0xe1 0x21 0xe0 0x0 0x0 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x1 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x3 0x1 0x0 0x0 0x0 0x0 0x0 0x0 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x0 0xe0 0xe0 0xc0 0xc1 0x83 0x87 0x8e 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x9c 0x8e 0x87 0x83 0x81 0x80 0x80 0x0 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x0 0xc0 0xf0 0xff 0xf0 0xc0 0xf 0xef 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0xe7 0xc7 0xc2 0x82 0x82 0x82 0x82 0x82 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x0 0xe0 0xe0 0xc0 0xd8 0x9e 0x9f 0x9e 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x98 0x80 0x9f 0x80 0x98 0x9e 0x9f 0x9e 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x98 0x0 0x8 0x10 0x30 0x60 0xec 0xcf 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x8f 0xcf 0xec 0x60 0x30 0x10 0x8 0x0 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x0 0x0 0x42 0x84 0x8c 0x18 0x38 0x70 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0xe0 0x70 0x38 0x18 0x8c 0x84 0x42 0x0 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x0 0x0 0x0 0xfe 0x0 0x3e 0xbe 0x9c 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x1c 0x8 0x8 0x8 0x8 0x8 0x8 0x8 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x0 0x0 0x0 0x0 0x0 0x0 0xfe 0x0 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x6 0x1e 0xfe 0x1e 0x6 0x0 0xfe 0x0 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0xfe 0x0 0x0 0x0 0x0 0x0 0x0 0x0 
	0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 